package Ga.Design;
import java.util.*;

public abstract class GeneticAlgorithm {
	public static Random randomGenerator;
	private ArrayList<IIndividual> population;
	
	private int INITIAL_POPULATION = 100;	
	private int P_MUTATION = 10;
	private int P_CROSSOVER = 10;
	
	public GeneticAlgorithm()
	{
		this.population = new ArrayList<IIndividual>();
		GeneticAlgorithm.randomGenerator = new Random();
	}
		
	public void initialize()
	{
		for(int i = 0; i < this.INITIAL_POPULATION; i++)
		{
			this.population.add(this.getNewIndivual());
		}
	}
	
	public void evaluatePopulation()
	{
		Collections.sort(this.population);
		
		ArrayList<IIndividual> children = new ArrayList<IIndividual>();
		
		for (int i = 0; i < this.population.size(); i++)
		{
			IIndividual currentIndiv = this.population.get(i);
			if(this.doMutation())
			{
				currentIndiv.Mutate();
			}
			if(this.doCrossOver() && this.population.size() > 1)
			{
				IIndividual mate = null;
				if(i == 0) 
					mate = this.population.get(i+1);
				else
					mate = this.population.get(i-1);
				
				children.add(currentIndiv.CrossOver(mate));
			}
		}
		
		for(int i = 0; i < children.size(); i++)
		{
			int index = this.population.size() - 1 - i;
			this.population.set(index, children.get(i));
		}
	}

	private boolean doCrossOver() 
	{
		return (GeneticAlgorithm.randomGenerator.nextInt(100) < this.P_CROSSOVER);
	}

	private boolean doMutation() 
	{
		return (GeneticAlgorithm.randomGenerator.nextInt(100) < this.P_MUTATION);
	}
	
	public ArrayList<IIndividual> getPopulation()
	{
		return this.population;
	}
	
	protected abstract IIndividual getNewIndivual();
	
	protected abstract boolean finished();
	
	public abstract void show(); 
}